#ifndef ODN_BASEGAME_H
#define ODN_BASEGAME_H

#include <opal\opal.h>
#include <ogre\Ogre.h>
#include <ogre\OgreKeyEvent.h>
#include <ogre\OgreEventListeners.h>

#include "ODN_GameState.h"
#include "ODN_InputDevice.h"
#include "ODN_Containers.h"
#include "ODN_GameWorld.h"
#include "ODN_Maths.h"
#include "ODN_ModelEntity.h"
#include "ODN_ModelBit.h"

#define MODEL_PATH "models\\"

namespace ouden {

class CBaseGame : public Ogre::FrameListener, public Ogre::KeyListener
{
	public:
		CBaseGame();
		virtual ~CBaseGame();
		
		//Main function to begin the game
		void start();
		
		//Game state management functions
		void changeState(CGameState* state);
		void pushState(CGameState* state);
		void popState();
		
		//Entity factories
		//CExplosion* createExplosion(Vector pos, Scalar size, Scalar force);
		void createModelEntity(String name, String modelFile, Vector pos = Vector(0, 0, 0), Angle orientation = 0);
		
	protected:
		
		//Game events
		//TODO: Maybe wrap these two functions to be onFrameStart and also think about onTick
		virtual bool frameStarted(const Ogre::FrameEvent &evt);
		virtual bool frameEnded(const Ogre::FrameEvent &evt);
		//virtual void onKeyDown(short keycode) 		{}
		//virtual void onKeyUp(short keycode) 		{}
		
		//Override this to create and initialise all scene elements
		//virtual void createScene() = 0;
		
		//Override this to destroy and clean up all the scene elements
		//virtual void destroyScene() = 0;
		
		
		//Game objects
		Ogre::Root*				m_pRoot; 			//Root Ogre object provides access to Ogre engine
		Ogre::SceneManager* 	m_pSceneMgr;		//Ogre Scene manager object
		Ogre::Camera* 			m_pCamera;			//Main game camera
		Ogre::RenderWindow* 	m_pWindow;			//Main renderer window
		Ogre::EventProcessor* 	m_pEventProcessor; 	//Ogre event processor for setting up input
		//Ogre::InputReader* 		m_pInputReader;		//Ogre input reading device
		opal::Simulator* 		m_pSimulator;		//Physics simulator
		CInputDevice* 			m_pInputDevice; 	//Unbuffered input reader
		//CGameStateMgr* 			m_pGameStateMgr; 	//Game state manager object
		CGameWorld* 			m_pGameWorld;		//Game world object which holds all game entities
		
		bool m_bFinished; 		//If true then exits main loop on next frame
		
		//Ogre Keylistener events redirect to onKeyDown and onKeyUp events in the current game state class
		virtual void 	keyClicked (Ogre::KeyEvent *e);
		virtual void 	keyPressed (Ogre::KeyEvent *e);
		virtual void 	keyReleased (Ogre::KeyEvent *e);
		
	private:
		
		//Main engine initialisation function called by run()
		bool init();
		
		//Loads all game resources as specified in the resources.cfg file
		bool loadResources();
				
		//Stack of current game states
		Array<CGameState*> m_pGameStates;
	
};

} //namespace ouden

#endif // ODN_BASEGAME_H
